
 /*
   +--------------------------------------------------------
   |
   | Name        : TDG.C (New)
   |
   | Description : Test Data Generator
   |
   | Version No. : 2.0
   |
   +--------------------------------------------------------
 */

 /* include files */
 #include <stdio.h>
 #include <conio.h>
 #include <math.h>

 #define MAXCHARSPERLINE  255
 #define RECORDSEPARATOR  '\n'

 /* structure for parameters */
 struct paramnode
  {
    char paramname[20] ;  /* parameter name */
    char type ;  /* C-Char, I-Int, R-Real L-long */
    unsigned char uprbound[20] , lwrbound[20] ; /* upper & lower bounds */
   } ;

 /* structure of each node of linked list for input
    source file */
 struct node
  {
    char *data ;
    struct node *next ;
   } ;

 /* global variables */
 struct paramnode paramtab[20] ;
 char fnprototype[MAXCHARSPERLINE] , outfile[64] , scrfile[64] ;
 int count , numrecords , recordlen ;
 struct node *head , *p ;

 /*
    Function Name : FreeList
    Call With     : None
    Returns       : None
    Description   : This function frees the linked list which has been
                    created after reading the input file
 */
 void FreeList (void)
  {
    struct node *gen ;

    gen = head -> next ;
    while ( gen -> next )
     {
       free (head -> data) ;
       free (head) ;
       head = gen ;
       gen = gen -> next ;
      }
   }

 /*
    Function Name : ReadAFile
    Call With     : char *fname - name of the file to read
    Returns       : int  0 - success
                        -1 - failure
    Description   : This function reads the input file and stores the
                    contents in a linked list
 */

 int ReadAFile (fname)
 char *fname ;
  {
    FILE *fp ;
    char c , temp[80] ;

    if (( head = (struct node *) malloc (sizeof (struct node))) == NULL )
     {
       printf ("Not Enough Memory !!! Terminating Program.") ;
       return (-1) ;
      }

    head -> data = NULL ;
    head -> next = NULL ;

    p = head ;

    strcpy (temp,fname) ;
    strcat (temp,".inp") ;

    if (( fp = fopen (temp,"r")) == NULL )
     {
       printf ("Cannot Open File !!! Terminating Program.") ;
       FreeList () ;
       return (-1) ;
      }

    while ( ( c = getc (fp)) != EOF )
     {
       ungetc (c,fp) ;
       fgets (temp,MAXCHARSPERLINE,fp) ;

       if ( temp[0] != '#' && temp[0] != ' ' && temp[0] != '\n' )
        {
          if (( p -> next = (struct node *) malloc (sizeof (struct node))) == NULL )
           {
             printf ("Not Enough Memory !!! Terminating Program.") ;
             FreeList () ;
             return (-1) ;
            }

          p = p -> next ;
          if (( p -> data = (char *) malloc (sizeof (char) * (strlen (temp) + 1))) == NULL )
           {
             printf ("Not Enough Memory !!! Terminating Program.") ;
             FreeList () ;
             return (-1) ;
            }

          strcpy (p -> data,temp) ;
          p -> next = NULL ;
         }
      }

    return (0) ;
   }

 /*
    Function Name : SetBoundsForParam
    Call With     : int idx - the index of the paramater
    Returns       : None
    Description   : This function sets the upper and lower bounds of
                    a parameter, after reading them from the input file
 */
 void SetBoundsForParam (idx)
 int idx ;
  {
    struct node *p ;
    char temp1[80] , temp2[80] ;

    p = head -> next ;
    while ( p )
     {
       strcpy (temp1,p -> data) ;
       if ( strcmp (strtok (temp1,":"),"Upper Bound ") == 0 )
        {
          if ( strcmp (paramtab[idx].paramname,strtok (NULL," \n")) == 0 )
           {
             strtok (NULL," \n") ;
             strcpy (paramtab[idx].uprbound,strtok (NULL,"\n")) ;
            }
          p = p -> next ;
          strcpy (temp2,p -> data) ;
          if ( strcmp (strtok (temp2,":"),"Lower Bound ") == 0 )
           {
             if ( strcmp (paramtab[idx].paramname,strtok (NULL," \n")) == 0 )
              {
                strtok (NULL," \n") ;
                strcpy (paramtab[idx].lwrbound,strtok (NULL,"\n")) ;
               }
            }
          else
           {
             printf ("\nNo Lower Bound Specified\n") ;
             FreeList () ;
             exit (-1) ;
            }
         }
       p = p -> next ;
      }
   }

 /*
    Function Name : ParsePrototype
    Call With     : None
    Returns       : None
    Description   : This function extracts the function name, the
                    parameter names, and their types from the function
                    prototype that has been given
 */
 void ParsePrototype (void)
  {
    int i , j ;
    char gen[20] , type ;

    /* separate the prototype to get the parameters names
       and their types */
    count = 0 ;
    for ( i = 0 ; fnprototype[i] != '(' ; i++ ) ;
    if ( fnprototype[i] == '(')
     {
       i++ ;
       for ( ; fnprototype[i] != ')' ; )
        {
          for ( ; fnprototype[i] == ' ' ; i++ ) ;

          for ( j = 0 ; fnprototype[i] != ' ' ; i++ , j++ )
            gen[j] = fnprototype[i] ;
          gen[j] = '\0' ;

          type = ' ' ;
          if ( strcmp (gen,"int") == 0 )
            type = 'I' ;
          else
           {
             if ( strcmp (gen,"long") == 0 )
               type = 'L' ;
             else
              {
                if ( strcmp (gen,"char") == 0 )
                  type = 'C' ;
                else
                  if ( ( strcmp (gen,"float") == 0 ) || strcmp (gen,"double") == 0 )
                    type = 'R' ;
               }
            }

          for ( ; fnprototype[i] == ' ' ; i++ ) ;

          for ( j = 0 ; fnprototype[i] != ',' && fnprototype[i] != ')' ; i++ , j++ )
            gen[j] = fnprototype[i] ;
          gen[j] = '\0' ;

          /* store parameter name */
          strcpy (paramtab[count].paramname,gen) ;

          /* store parameter type */
          paramtab[count].type = type ;

          /* get the upper & lower bounds values for a variable */
          SetBoundsForParam (count) ;

          switch ( paramtab[count].type )
           {
             case 'I' :
                  if ( atoi (paramtab[count].uprbound) < atoi (paramtab[count].lwrbound) )
                   {
                     printf ("\nUpper Bound LESS Than Lower Bound\n") ;
                     FreeList () ;
                     exit (-1) ;
                    }
                  break ;

             case 'R' :
                  if ( atof (paramtab[count].uprbound) < atof (paramtab[count].lwrbound) )
                   {
                     printf ("\nUpper Bound LESS Than Lower Bound\n") ;
                     FreeList () ;
                     exit (-1) ;
                    }
                  break ;

             case 'L' :
                  if ( atol (paramtab[count].uprbound) < atol (paramtab[count].lwrbound) )
                   {
                     printf ("\nUpper Bound LESS Than Lower Bound\n") ;
                     FreeList () ;
                     exit (-1) ;
                    }
                  break ;

             case 'C' :
                  if ( paramtab[count].uprbound[0] < paramtab[count].lwrbound[0] )
                   {
                     printf ("\nUpper Bound LESS Than Lower Bound\n") ;
                     FreeList () ;
                     exit (-1) ;
                    }
                  break ;
            }

          /* increment number of parameters count */
          count++ ;
          /* no more parameters, stop */
          if ( fnprototype[i] == ')' )
            break ;
          else
            i++ ;
         }
      }
   }

 /* extract the function prototype */
 void ExtractFunctionProto ()
  {
    char temp1[80] ;
    struct node *p ;

    p = head -> next ;
    while ( p )
     {
       strcpy (temp1,p -> data) ;
       if ( strcmp (strtok (temp1,":"),"Function Prototype ") == 0 )
        {
          strcpy (fnprototype,strtok (NULL,"\n")) ;
          break ;
         }
       p = p -> next ;
      }

    ParsePrototype () ;
   }

 /* extract the name of the file containing the function */
 char *ExtractIncludeName ()
  {
    char temp1[80] ;
    struct node *p ;

    p = head -> next ;
    while ( p )
     {
       strcpy (temp1,p -> data) ;
       if ( strcmp (strtok (temp1,":"),"Function Filename ") == 0 )
         return (strtok (NULL," \n")) ;
       p = p -> next ;
      }

    return (NULL) ;
   }

 /* write the include statement */
 void WriteIncludeStmt (fp)
 FILE *fp ;
  {
    char *p = "\n #include \"" ;

    fprintf (fp,p) ;
    fprintf (fp,"%s\"\n",ExtractIncludeName ()) ;
   }

 /* display the parameter table */
 void DisplayVarTab ()
  {
    int i ;

    printf ("\n\n               **  PARAMETER  TABLE  INFORMATION  **\n") ;
    printf ("\n                NAME : TYPE  : U BOUND : L BOUND\n") ;
    for ( i = 0 ; i < count ; i++ )
     {
       printf ("\n%20s : ",paramtab[i].paramname) ;
       switch ( paramtab[i].type )
        {
          case 'I' :
               printf ("Int   : %7s : %7s",paramtab[i].uprbound,paramtab[i].lwrbound) ;
               break ;

          case 'L' :
               printf ("Long  : %7s : %7s",paramtab[i].uprbound,paramtab[i].lwrbound) ;
               break ;

          case 'R' :
               printf ("Float : %7s : %7s",paramtab[i].uprbound,paramtab[i].lwrbound) ;
               break ;

          case 'C' :
               printf ("Char  : %7s : %7s",paramtab[i].uprbound,paramtab[i].lwrbound) ;
               break ;
         }
      }
   }

 /* get the number of records to be generated */
 char *GetRecordsToGenerate ()
  {
    char temp1[80] ;
    struct node *p ;

    p = head -> next ;
    while ( p )
     {
       strcpy (temp1,p -> data) ;
       if ( strcmp (strtok (temp1,":"),"Records To Generate ") == 0 )
         return (strtok (NULL,"\n")) ;
       p = p -> next ;
      }

    return (NULL) ;
   }

 /* generate test data */
 void GenerateTestData ()
  {
    FILE *fp ;
    int upint , lwint , i , j , inum ;
    float upfloat , lwfloat , fnum ;
    unsigned char upchar , lwchar , cnum ;
    long uplong , lwlong , lnum ;

    numrecords = atoi (GetRecordsToGenerate ()) ;

    /* open file */
    if (( fp = fopen (outfile,"w")) == NULL )
     {
       printf ("\n\nUnable To Open File For Output. Terminating Program") ;
       return ;
      }

    /* generate test data */
    printf ("\n\nGenerating %d Records. Please Wait...",numrecords) ;
    for ( i = 0 ; i < numrecords ; i++ )
     {
       fprintf (fp,"%5d ",i) ;
       for ( j = 0 ; j < count ; j++ )
        {
          switch ( paramtab[j].type )
           {
             case 'I' :
                  upint = atoi (paramtab[j].uprbound) ;
                  lwint = atoi (paramtab[j].lwrbound) ;
                  while ( 1 )
                   {
                     /* generate a random number */
                     inum = rand () ;
                     /* check that the number is valid */
                     if ( inum <= upint && inum >= lwint )
                      {
                        fprintf (fp,"%10d ",inum) ;
                        break ;
                       }
                    }
                  break ;

             case 'L' :
                  uplong = atol (paramtab[j].uprbound) ;
                  lwlong = atol (paramtab[j].lwrbound) ;
                  while ( 1 )
                   {
                     /* generate a random number */
                     lnum = rand () ;
                     /* check that the number is valid */
                     if ( lnum <= uplong && lnum >= lwlong )
                      {
                        fprintf (fp,"%20d ",lnum) ;
                        break ;
                       }
                    }
                  break ;

             case 'R' :
                  upfloat = atof (paramtab[j].uprbound) ;
                  lwfloat = atof (paramtab[j].lwrbound) ;
                  while ( 1 )
                   {
                     /* generate a random number */
                     fnum = rand () ;
                     /* generate a float */
                     fnum = fnum * 1.2 ;
                     /* check that the number is valid */
                     if ( fnum <= upfloat && fnum >= lwfloat )
                      {
                        fprintf (fp,"%15f ",fnum) ;
                        break ;
                       }
                    }
                  break ;

             case 'C' :
                  upchar = paramtab[j].uprbound[0] ;
                  lwchar = paramtab[j].lwrbound[0] ;
                  while ( 1 )
                   {
                     /* generate a random number */
                     cnum = rand () ;
                     /* check taht the char is valid */
                     if ( cnum <= upchar && cnum >= lwchar )
                      {
                        fprintf (fp,"%c ",cnum) ;
                        break ;
                       }
                    }
                  break ;
            }
         }
       /* put the record separator */
       fprintf (fp,"%c",RECORDSEPARATOR) ;
      }

    fclose (fp) ;
   }

 /* find out the length of each record in the test data file */
 void CalculateRecordLength ()
  {
    int i ;

    for ( i = 0 , recordlen = 6 ; i < count ; i++ )
     {
       switch ( paramtab[i].type )
        {
          case 'I' :
               recordlen += 11 ;
               break ;

          case 'L' :
               recordlen += 21 ;
               break ;

          case 'R' :
               recordlen += 16 ;
               break ;

          case 'C' :
               recordlen += 2 ;
               break ;
         }
      }

    recordlen += 2 ;
   }

 /* get the name of the function that has to be tested */
 char *GetFunctionName ()
  {
    int i ;
    char temp[40] , *tok , *tok1 ;

    tok = strtok (fnprototype,"(") ;

    strtok (tok," ") ;
    tok1 = strtok (NULL," ") ;
    if ( tok1 == NULL )
      return tok ;
    else
      return tok1 ;
   }

 /* generate the function script that will read the test data
    from the test data file and use the data to test the
    function */
 void GenerateScriptFile ()
  {
    /* declare the strings that will be used to generate
       the function */
    char *p1[] = { "\n",
                   " #include <stdio.h>\n",
                   " #include <math.h>\n"
                  } ;
    char *p8[] = {
                   "\n",
                   " #define LEN "
                  } ;
    char *p2[] = { " void TestAFunction (void)\n",
                   "  {\n",
                   "    FILE *fp ;\n",
                   "    char rec[LEN] , c , *tok ;\n"
                  } ;
    char *p3 =  "\n    if (( fp = fopen (\"" ;
    char *p4[] = { "\",\"r\")) == NULL )\n",
                   "     {\n",
                   "       printf (\"\\nError opening test data file\") ;\n",
                   "       return ;\n",
                   "      }\n",
                   "\n",
                   "    while ( (c = getc (fp)) != EOF )\n",
                   "     {\n",
                   "       ungetc (c,fp) ;\n",
                   "       fgets (rec,LEN,fp) ;\n\n"
                  } ;
    char *p5 = "       tok = strtok (rec,\" \\n\") ;\n" ;
    char *p6 = "       tok = strtok (NULL,\" \\n\") ;\n" ;
    char *p7[] = { "\n",
                   "      }\n\n",
                   "    fclose (fp) ;\n",
                   "   }\n",
                   "\n",
                   " void main (void)\n",
                   "  {\n",
                   "    float dummy ;\n",
                   "\n",
                   "    printf (\"Enter some real number : \") ;\n",
                   "    scanf (\"%%f\",&dummy) ;\n",
                   "\n",
                   "    TestAFunction () ;\n",
                   "   }\n"
                  } ;
    char *conv[] = { " = atoi (tok) ;\n",
                     " = atol (tok) ;\n",
                     " = atof (tok) ;\n",
                     " = tok[0] ;\n"
                    } ;

    int num_p1 = 3 , num_p2 = 4 , num_p4 = 10 , num_p7 = 14 , num_p8 = 2 ;
    int i ;
    FILE *fp ;

    if (( fp = fopen (scrfile,"w")) == NULL )
     {
       printf ("\nError in opening script file") ;
       return ;
      }

    /* generate script file */
    for ( i = 0 ; i < num_p1 ; i++ )
      fprintf (fp,p1[i]) ;

    WriteIncludeStmt (fp) ;

    for ( i = 0 ; i < num_p8 ; i++ )
      fprintf (fp,p8[i]) ;
    fprintf (fp," %d\n",recordlen) ;

    for ( i = 0 ; i < num_p2 ; i++ )
      fprintf (fp,p2[i]) ;

    /* declare the parameters as variabels in the function */
    for ( i = 0 ; i < count ; i++ )
     {
       fprintf (fp,"    ") ;
       switch ( paramtab[i].type )
        {
          case 'I' :
               fprintf (fp,"int ") ;
               break ;

          case 'L' :
               fprintf (fp,"long ") ;
               break ;

          case 'R' :
               fprintf (fp,"float ") ;
               break ;

          case 'C' :
               fprintf (fp,"char ") ;
               break ;
         }

       fprintf (fp,"%s ;\n",paramtab[i].paramname) ;
      }

    fprintf (fp,p3) ;
    fprintf (fp,"%s",outfile) ;

    for ( i = 0 ; i < num_p4 ; i++ )
      fprintf (fp,p4[i]) ;

    fprintf (fp,p5) ;
    for ( i = 0 ; i < count ; i++ )
     {
       fprintf (fp,p6) ;
       fprintf (fp,"       %s",paramtab[i].paramname) ;
       switch ( paramtab[i].type )
        {
          case 'I' :
               fprintf (fp,"%s",conv[0]) ;
               break ;

          case 'L' :
               fprintf (fp,"%s",conv[1]) ;
               break ;

          case 'R' :
               fprintf (fp,"%s",conv[2]) ;
               break ;

          case 'C' :
               fprintf (fp,"%s",conv[3]) ;
               break ;
         }
      }

    fprintf (fp,"\n       %s (",GetFunctionName ()) ;
    for ( i = 0 ; i < count ; i++ )
     {
       fprintf (fp,"%s",paramtab[i].paramname) ;
       if ( i < (count - 1) )
         fprintf (fp,",") ;
      }
    fprintf (fp,") ;") ;

    for ( i = 0 ; i < num_p7 ; i++ )
      fprintf (fp,p7[i]) ;

    /* close script file */
    fclose (fp) ;
   }

 void GenerateProtoInpFile (fname)
 char *fname ;
  {
    char *p[] = { "Function Prototype : ",
                  "Upper Bound :  = ",
                  "Lower Bound :  = ",
                  "Records To Generate : ",
                  "Function Filename : "
                 } ;
    int num_p = 5 , i ;
    FILE *fp ;

    if (( fp = fopen (fname,"w")) == NULL )
     {
       printf ("\nUnable to open file for writing input specs\n") ;
       return ;
      }

    for ( i = 0 ; i < num_p ; i++ )
      fprintf (fp,"%s\n",p[i]) ;

    fclose (fp) ;
   }

 int main (argc,argv)
 int argc ;
 char *argv[] ;
  {
    char *s ;
    float dummy ;

    if ( argc < 2 )
     {
       printf ("Usage : TDG [filename].INP [/INP [Proto]]") ;
       exit (-1) ;
      }

    printf ("Enter some real number : ") ;
    scanf ("%f",&dummy) ;

    fflush (stdin) ;

    clrscr () ;

    strcpy (outfile,argv[1]) ;
    strcat (outfile,".out") ;
    strcpy (scrfile,argv[1]) ;
    strcat (scrfile,".scr") ;

    printf ("\n\nReading Input File : %s.INP",strupr (argv[1])) ;
    if ( ReadAFile (argv[1]) == -1 )
      exit (-1) ;

    ExtractFunctionProto () ;

    DisplayVarTab () ;

    printf ("\n\nGenerating Data File : %s.OUT",strupr (argv[1])) ;

    GenerateTestData () ;

    CalculateRecordLength () ;

    printf ("\n\nGenerating Script File : %s.SCR",strupr (argv[1])) ;

    GenerateScriptFile () ;

    FreeList () ;

    if ( strcmp (argv[2],"/INP") == 0 )
     {
       if ( argc == 4 )
        {
          printf ("\n\nGenerating Prototype Input File : %s",strupr (argv[3])) ;

          GenerateProtoInpFile (argv[3]) ;
         }
       else
        {
          printf ("\n\nGenerating Prototype Input File : TEMP.INP") ;

          GenerateProtoInpFile ("temp.inp") ;
         }
      }

    exit (0) ;
   }

 /*----- END -----*/
